use nacos_core::traits::{NamingService, ConfigService};
use nacos_core::{ServiceInstance, ConfigInfo, Result, NacosError};
use std::collections::HashMap;
use std::sync::Arc;

#[derive(Debug, Clone)]
struct MockNamingService;

#[async_trait::async_trait]
impl NamingService for MockNamingService {
    async fn register_instance(
        &self,
        namespace: &str,
        service_name: &str,
        instance: ServiceInstance,
    ) -> Result<()> {
        println!("Register instance: {}.{}@{}:{}", service_name, namespace, instance.ip, instance.port);
        Ok(())
    }

    async fn deregister_instance(
        &self,
        namespace: &str,
        service_name: &str,
        ip: &str,
        port: u16,
    ) -> Result<()> {
        println!("Deregister instance: {}.{}@{}:{}", service_name, namespace, ip, port);
        Ok(())
    }

    async fn get_instances(
        &self,
        namespace: &str,
        service_name: &str,
        healthy_only: bool,
    ) -> Result<Vec<ServiceInstance>> {
        println!("Get instances: {}.{} (healthy_only: {})", service_name, namespace, healthy_only);
        Ok(vec![ServiceInstance {
            ip: "127.0.0.1".to_string(),
            port: 8080,
            weight: 1.0,
            healthy: true,
            enabled: true,
            ephemeral: true,
            cluster_name: "default".to_string(),
            service_name: service_name.to_string(),
            namespace: namespace.to_string(),
            metadata: HashMap::new(),
        }])
    }

    async fn list_services(&self, namespace: &str, page: u32, page_size: u32) -> Result<Vec<String>> {
        println!("List services: {} (page: {}, page_size: {})", namespace, page, page_size);
        Ok(vec!["test-service".to_string()])
    }

    async fn start(&self) -> Result<()> {
        Ok(())
    }

    async fn shutdown(&self) -> Result<()> {
        Ok(())
    }
}

#[derive(Debug, Clone)]
struct MockConfigService;

#[async_trait::async_trait]
impl ConfigService for MockConfigService {
    async fn publish_config(&self, config: ConfigInfo) -> Result<bool> {
        println!("Publish config: {}.{}.{} = {}", 
            config.namespace, config.group, config.data_id, config.content);
        Ok(true)
    }

    async fn get_config(&self, namespace: &str, group: &str, data_id: &str) -> Result<ConfigInfo> {
        println!("Get config: {}.{}.{}"
            , namespace, group, data_id);
        Ok(ConfigInfo {
            namespace: namespace.to_string(),
            group: group.to_string(),
            data_id: data_id.to_string(),
            content: "test-content".to_string(),
            md5: Some("d41d8cd98f00b204e9800998ecf8427e".to_string()),
            last_modified: Some(chrono::Utc::now()),
        })
    }

    async fn delete_config(&self, namespace: &str, group: &str, data_id: &str) -> Result<bool> {
        println!("Delete config: {}.{}.{}"
            , namespace, group, data_id);
        Ok(true)
    }

    async fn add_listener(&self, namespace: &str, group: &str, data_id: &str, listener_id: &str) -> Result<()> {
        println!("Add listener: {}.{}.{} for {}", namespace, group, data_id, listener_id);
        Ok(())
    }

    async fn remove_listener(&self, namespace: &str, group: &str, data_id: &str, listener_id: &str) -> Result<()> {
        println!("Remove listener: {}.{}.{} for {}", namespace, group, data_id, listener_id);
        Ok(())
    }

    async fn start(&self) -> Result<()> {
        Ok(())
    }

    async fn shutdown(&self) -> Result<()> {
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use nacos_cluster::ClusterConfig;
    use nacos_naming::NamingConfig;
    use nacos_config::ConfigConfig;
    use nacos_network::NetworkConfig;
    use nacos_server::server::{NacosServer, ServerConfig};

    #[tokio::test]
    async fn test_api_integration() {
        let config = ServerConfig {
            port: 8849, // 使用不同端口避免冲突
            ip: "127.0.0.1".to_string(),
            cluster: ClusterConfig::default(),
            naming: NamingConfig::default(),
            config: ConfigConfig::default(),
            network: NetworkConfig::default(),
            tls_enabled: false,
            max_connections: 100,
            request_timeout: 5000,
        };

        let server = NacosServer::new(config).unwrap();
        
        // 启动服务器
        server.start().await.unwrap();
        
        // 等待服务器启动
        tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
        
        // 测试健康检查
        let health = server.health_check().await.unwrap();
        assert!(health);
        
        // 停止服务器
        server.stop().await.unwrap();
    }

    #[tokio::test]
    async fn test_naming_api() {
        let naming_service = Arc::new(MockNamingService);
        let config_service = Arc::new(MockConfigService);
        
        // 测试命名服务API
        let instance = ServiceInstance {
            ip: "127.0.0.1".to_string(),
            port: 8080,
            weight: 1.0,
            healthy: true,
            enabled: true,
            ephemeral: true,
            cluster_name: "default".to_string(),
            service_name: "test-service".to_string(),
            namespace: "test-ns".to_string(),
            metadata: HashMap::new(),
        };

        let result = naming_service.register_instance("test-ns", "test-service", instance).await;
        assert!(result.is_ok());

        let instances = naming_service.get_instances("test-ns", "test-service", true).await;
        assert!(instances.is_ok());
        assert_eq!(instances.unwrap().len(), 1);
    }

    #[tokio::test]
    async fn test_config_api() {
        let config_service = Arc::new(MockConfigService);
        
        // 测试配置服务API
        let config_info = ConfigInfo {
            namespace: "test-ns".to_string(),
            group: "test-group".to_string(),
            data_id: "test-data".to_string(),
            content: "test-content".to_string(),
            md5: None,
            last_modified: None,
        };

        let result = config_service.publish_config(config_info).await;
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), true);

        let config = config_service.get_config("test-ns", "test-group", "test-data").await;
        assert!(config.is_ok());
        assert_eq!(config.unwrap().content, "test-content");
    }
}